package com.file.parser;

import com.file.bo.CDBDCHousingInfoQueryRecord;
import com.file.bo.CDBDCNetContractInfoQueryRecord;
import com.file.bo.CDBDCPersonalHousingInfoQueryRecord;
import com.file.bo.CDBDCTradeHousingInfoVerificationRecord;
import com.file.bo.ResponseData;
import com.file.constant.ErrorCode;
import com.file.util.JsonUtils;
import java.io.File;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.stream.Collectors;

import com.google.common.base.Splitter;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.apache.pdfbox.pdmodel.PDDocument;
import technology.tabula.ObjectExtractor;
import technology.tabula.Page;
import technology.tabula.PageIterator;
import technology.tabula.Rectangle;
import technology.tabula.Table;
import technology.tabula.detectors.SpreadsheetDetectionAlgorithm;
import technology.tabula.extractors.SpreadsheetExtractionAlgorithm;

@Slf4j
public class CDBDCPdfParser extends BasePdfParser{

    public ResponseData<String> parseCDBDCPdfToJson(String daId, String filePath) {
        log.info("parseCDBDCPdfToJson started, daId:{}", daId);
        String json = null;

        try {
            int fileType = getFileType(filePath);
            switch (fileType) {
                case 0:
                case 4:
                    CDBDCPersonalHousingInfoQueryRecord personalHousingInfoQueryRecord = parsePersonalHousingInfoQueryRecord(filePath);
                    json = JsonUtils.convertObjectToJson(personalHousingInfoQueryRecord);
                    break;
                case 1:
                    CDBDCHousingInfoQueryRecord housingInfoQueryRecord = parseHousingInfoQueryRecord(filePath);
                    json = JsonUtils.convertObjectToJson(housingInfoQueryRecord);
                    break;
                case 2:
                    CDBDCNetContractInfoQueryRecord netContractInfoQueryRecord = parseNetContractInfoQueryRecord(filePath);
                    json = JsonUtils.convertObjectToJson(netContractInfoQueryRecord);
                    break;
                case 3:
                    CDBDCTradeHousingInfoVerificationRecord tradeHousingInfoVerificationRecord = parseTradeHousingInfoVerificationRecord(filePath);
                    json = JsonUtils.convertObjectToJson(tradeHousingInfoVerificationRecord);
                    break;
            }


        } catch (Exception e) {
            log.error("OnError|{}||{}|{}|{}|{}", ErrorCode.FILE_PARSE_EXCEPTION.getCode(), daId, "", "", "parseCDBDCPdfToJson failed", e);
            return new ResponseData<>(json, ErrorCode.FILE_PARSE_EXCEPTION.getCode(), ErrorCode.FILE_PARSE_EXCEPTION.getMsg());
        }

        log.info("parseCDBDCPdfToJson completed, daId:{}", daId);
        return new ResponseData<>(json, ErrorCode.SUCCESS.getCode(), ErrorCode.SUCCESS.getMsg());
    }

    private int getFileType(String filePath) {
        int fileType = 0;
        String pdfHeaderText = parsePdfHeaderText(filePath);
        if (pdfHeaderText.contains("个人住房信息查询记录") && pdfHeaderText.contains("无房屋查询记录")) {
            fileType = 4;
        } else if (pdfHeaderText.contains("个人住房信息查询记录")) {
            fileType = 0;
        } else if (pdfHeaderText.contains("房屋信息查询记录")) {
            fileType = 1;
        } else if (pdfHeaderText.contains("网签合同信息查询记录")) {
            fileType = 2;
        } else if (pdfHeaderText.contains("交易房屋信息核实记录")) {
            fileType = 3;
        }
        return fileType;
    }

    // 个人住房信息查询记录
    private CDBDCPersonalHousingInfoQueryRecord parsePersonalHousingInfoQueryRecord(String filePath) {
        CDBDCPersonalHousingInfoQueryRecord personalHousingInfoQueryRecord = parsePersonalHousingInfoQueryRecordHeader(filePath);
        List<List<String>> rowList = parseFileToRowList(filePath);
        parseListToBO(rowList, personalHousingInfoQueryRecord);
        return personalHousingInfoQueryRecord;
    }

    private CDBDCPersonalHousingInfoQueryRecord parsePersonalHousingInfoQueryRecordHeader(String filePath) {
        CDBDCPersonalHousingInfoQueryRecord personalHousingInfoQueryRecord = new CDBDCPersonalHousingInfoQueryRecord();
        CDBDCPersonalHousingInfoQueryRecord.FileInfo fileInfo = new CDBDCPersonalHousingInfoQueryRecord.FileInfo();
        String pdfText = getPdfTextByStripper2(filePath);
        pdfText = pdfText.replace(System.getProperty("line.separator", "\n"), "");

        String fileName = pdfText.substring(0, pdfText.indexOf("申请人：")).trim();
        String applicant = pdfText.substring(pdfText.indexOf("申请人：") + 4, pdfText.indexOf("验证码：")).trim();
        String verificationCode = pdfText.substring(pdfText.indexOf("验证码：") + 4, pdfText.indexOf("查询编号：")).trim();
        String queryNumber = pdfText.substring(pdfText.indexOf("查询编号：") + 5, pdfText.indexOf("申请信息")).trim();
        String queryRange = pdfText.substring(pdfText.indexOf("查询范围：") + 5, pdfText.indexOf("查询平台：")).trim();
        String queryPlatform = pdfText.substring(pdfText.indexOf("查询平台：") + 5, pdfText.indexOf("打印机构：")).trim();
        String printingMechanism = pdfText.substring(pdfText.indexOf("打印机构：") + 5, pdfText.indexOf("查询时点：")).trim();
        String queryTimePoint = pdfText.substring(pdfText.indexOf("查询时点：") + 5, pdfText.indexOf("特别提示：")).trim();
        String specialSuggestion = pdfText.substring(pdfText.indexOf("特别提示：") + 5, pdfText.lastIndexOf("第")).trim();

        fileInfo.setFileName(fileName);
        fileInfo.setApplicant(applicant);
        fileInfo.setVerificationCode(verificationCode);
        fileInfo.setQueryNumber(queryNumber);
        fileInfo.setQueryRange(queryRange);
        fileInfo.setQueryPlatform(queryPlatform);
        fileInfo.setPrintingMechanism(printingMechanism);
        fileInfo.setQueryTimePoint(queryTimePoint);
        fileInfo.setSpecialSuggestion(specialSuggestion);
        personalHousingInfoQueryRecord.setFileInfo(fileInfo);

        return personalHousingInfoQueryRecord;
    }

    // 房屋信息查询记录
    private CDBDCHousingInfoQueryRecord parseHousingInfoQueryRecord(String filePath) {
        CDBDCHousingInfoQueryRecord housingInfoQueryRecord = parseHousingInfoQueryRecordHeader(filePath);
        List<List<String>> rowList = parseFileToRowList(filePath);
        parseListToBO(rowList, housingInfoQueryRecord);
        // "历史变动信息"可能会存在未解析到的case
        // 如果list中包含空的"历史变动信息"记录, 默认第一页最后一条记录没有被解析到
        if (hasEmptyValueBo(housingInfoQueryRecord)) {
            parseHistoricalChangeInfo(filePath, housingInfoQueryRecord);
        }
        return housingInfoQueryRecord;
    }

    private CDBDCHousingInfoQueryRecord parseHousingInfoQueryRecordHeader(String filePath) {
        CDBDCHousingInfoQueryRecord houseInfoQueryRecord = new CDBDCHousingInfoQueryRecord();
        CDBDCHousingInfoQueryRecord.FileInfo fileInfo = new CDBDCHousingInfoQueryRecord.FileInfo();

        String pdfText = getPdfTextByStripper2(filePath);
        pdfText = pdfText.replace(System.getProperty("line.separator", "\n"), "");
        String fileName = pdfText.substring(0, pdfText.indexOf("业务件号：")).trim();
        String itemNumber = pdfText.substring(pdfText.indexOf("业务件号：") + 5, pdfText.indexOf("验证码：")).trim();
        String verificationCode = pdfText.substring(pdfText.indexOf("验证码：") + 4, pdfText.indexOf("查询编号：")).trim();
        String queryNumber = pdfText.substring(pdfText.indexOf("查询编号：") + 5, pdfText.indexOf("基本信息")).trim();
        String queryPlatform = pdfText.substring(pdfText.indexOf("查询平台：") + 5, pdfText.indexOf("打印机构：")).trim();
        String printingMechanism = pdfText.substring(pdfText.indexOf("打印机构：") + 5, pdfText.indexOf("查询时点：")).trim();
        String queryTimePoint = pdfText.substring(pdfText.indexOf("查询时点：") + 5, pdfText.indexOf("特别提示：")).trim();
        String specialSuggestion = pdfText.substring(pdfText.indexOf("特别提示：") + 5, pdfText.lastIndexOf("第")).trim();
        fileInfo.setFileName(fileName);
        fileInfo.setItemNumber(itemNumber);
        fileInfo.setVerificationCode(verificationCode);
        fileInfo.setQueryNumber(queryNumber);
        fileInfo.setQueryPlatform(queryPlatform);
        fileInfo.setPrintingMechanism(printingMechanism);
        fileInfo.setQueryTimePoint(queryTimePoint);
        fileInfo.setSpecialSuggestion(specialSuggestion);
        houseInfoQueryRecord.setFileInfo(fileInfo);
        return houseInfoQueryRecord;
    }

    // 网签合同信息查询记录
    private CDBDCNetContractInfoQueryRecord parseNetContractInfoQueryRecord(String filePath) {
        CDBDCNetContractInfoQueryRecord netContractInfoQueryRecord = parseNetContractInfoQueryRecordHeader(filePath);
        List<List<String>> rowList = parseFileToRowList(filePath);
        parseListToBO(rowList, netContractInfoQueryRecord);
        return netContractInfoQueryRecord;
    }

    private CDBDCNetContractInfoQueryRecord parseNetContractInfoQueryRecordHeader(String filePath) {
        CDBDCNetContractInfoQueryRecord netContractInfoQueryRecord = new CDBDCNetContractInfoQueryRecord();
        CDBDCNetContractInfoQueryRecord.FileInfo fileInfo = new CDBDCNetContractInfoQueryRecord.FileInfo();

        String pdfText = getPdfTextByStripper2(filePath);
        pdfText = pdfText.replace(System.getProperty("line.separator", "\n"), "");
        String fileName = pdfText.substring(0, pdfText.indexOf("验证码")).trim();
        String verificationCode = pdfText.substring(pdfText.indexOf("验证码：") + 4, pdfText.indexOf("查询编号")).trim();
        String queryNumber = pdfText.substring(pdfText.indexOf("查询编号：") + 5, pdfText.indexOf("基本信息")).trim();
        String queryPlatform = pdfText.substring(pdfText.indexOf("查询平台：") + 5, pdfText.indexOf("打印机构：")).trim();
        String printingMechanism = pdfText.substring(pdfText.indexOf("打印机构：") + 5, pdfText.indexOf("查询时点：")).trim();
        String queryTimePoint = pdfText.substring(pdfText.indexOf("查询时点：") + 5, pdfText.indexOf("特别提示：")).trim();
        String specialSuggestion = pdfText.substring(pdfText.indexOf("特别提示：") + 5, pdfText.lastIndexOf("第")).trim();
        fileInfo.setFileName(fileName);
        fileInfo.setVerificationCode(verificationCode);
        fileInfo.setQueryNumber(queryNumber);
        fileInfo.setQueryPlatform(queryPlatform);
        fileInfo.setPrintingMechanism(printingMechanism);
        fileInfo.setQueryTimePoint(queryTimePoint);
        fileInfo.setSpecialSuggestion(specialSuggestion);
        netContractInfoQueryRecord.setFileInfo(fileInfo);

        return netContractInfoQueryRecord;
    }

    // 交易房屋信息核实记录
    private CDBDCTradeHousingInfoVerificationRecord parseTradeHousingInfoVerificationRecord(String filePath) {
        CDBDCTradeHousingInfoVerificationRecord tradeHousingInfoVerificationRecord = parseTradeHousingInfoVerificationRecordHeader(filePath);
        List<List<String>> rowList = parseFileToRowList(filePath);
        parseListToBO(rowList, tradeHousingInfoVerificationRecord);
        // 如果解析后的"附号"的长度<3, 或者长度>3, 则默认是解析正常的
        // 如果"附号"的长度为3, 可能出现"附号"字段的实际长度大于3, 这种情况下会换行, 换行可能出现换行后的字段没发解析到(压线)
        if (tradeHousingInfoVerificationRecord.getBasicInfo().getAttachedNumber().length() == 3) {
            parseBasicInfoAttachedNumber(filePath, tradeHousingInfoVerificationRecord);
        }
        return tradeHousingInfoVerificationRecord;
    }

    private void parseBasicInfoAttachedNumber(String filePath, CDBDCTradeHousingInfoVerificationRecord tradeHousingInfoVerificationRecord) {
        try {
            String pdfHeaderText = parsePdfHeaderText2(filePath).replaceAll("\\s+", "");
            CDBDCTradeHousingInfoVerificationRecord.BasicInfo basicInfo = tradeHousingInfoVerificationRecord.getBasicInfo();
            String street = basicInfo.getStreet();
            String doorPlate = basicInfo.getDoorPlate();
            // "附号"前面的两个字段
            String frontTextOfAttachedNumber = street.concat(doorPlate);
            String buildingNumber = basicInfo.getBuildingNumber();
            String unit = basicInfo.getUnit();
            String floor = basicInfo.getFloor();
            // "附号"后面的三个字段
            String behindTextOfAttachedNumber = buildingNumber.concat(unit).concat(floor);
            // 截取从"附号"开始的pdfHeader
            String text = pdfHeaderText.substring(pdfHeaderText.indexOf(frontTextOfAttachedNumber) + frontTextOfAttachedNumber.length());
            String attachedNumber = text.substring(0, text.indexOf(behindTextOfAttachedNumber));
            basicInfo.setAttachedNumber(attachedNumber);
        } catch (Exception e) {
            log.error("parseBasicInfoAttachedNumber fail.", e);
        }
    }

    private CDBDCTradeHousingInfoVerificationRecord parseTradeHousingInfoVerificationRecordHeader(String filePath) {
        CDBDCTradeHousingInfoVerificationRecord tradeHousingInfoVerificationRecord = new CDBDCTradeHousingInfoVerificationRecord();
        CDBDCTradeHousingInfoVerificationRecord.FileInfo fileInfo = new CDBDCTradeHousingInfoVerificationRecord.FileInfo();
        String pdfHeaderText = parsePdfHeaderText(filePath);

        String fileName = pdfHeaderText.substring(0, pdfHeaderText.indexOf("核实申请人：")).trim();
        String verificationApplicant = pdfHeaderText.substring(pdfHeaderText.indexOf("核实申请人：") + 6, pdfHeaderText.indexOf("; 业务件号")).trim();
        String itemNumber = pdfHeaderText.substring(pdfHeaderText.indexOf("业务件号：") + 5, pdfHeaderText.indexOf("验证码：")).trim();
        String verificationCode = pdfHeaderText.substring(pdfHeaderText.indexOf("验证码：") + 4, pdfHeaderText.indexOf("查询编号：")).trim();
        String queryNumber = pdfHeaderText.substring(pdfHeaderText.indexOf("查询编号：") + 5, pdfHeaderText.indexOf("基本信息")).trim();
        String verificationPlatform = pdfHeaderText.substring(pdfHeaderText.indexOf("核实平台：") + 5, pdfHeaderText.indexOf("打印机构：")).trim();
        String printingMechanism = pdfHeaderText.substring(pdfHeaderText.indexOf("打印机构：") + 5, pdfHeaderText.indexOf("核实时点：")).trim();
        String verificationTimePoint = pdfHeaderText.substring(pdfHeaderText.indexOf("核实时点：") + 5, pdfHeaderText.indexOf("特别提示：")).trim();
        String specialSuggestion = pdfHeaderText.substring(pdfHeaderText.indexOf("特别提示：") + 5, pdfHeaderText.lastIndexOf("第")).trim();

        fileInfo.setFileName(fileName);
        fileInfo.setVerificationApplicant(verificationApplicant);
        fileInfo.setItemNumber(itemNumber);
        fileInfo.setVerificationCode(verificationCode);
        fileInfo.setQueryNumber(queryNumber);
        fileInfo.setVerificationPlatform(verificationPlatform);
        fileInfo.setPrintingMechanism(printingMechanism);
        fileInfo.setVerificationTimePoint(verificationTimePoint);
        fileInfo.setSpecialSuggestion(specialSuggestion);
        tradeHousingInfoVerificationRecord.setFileInfo(fileInfo);

        return tradeHousingInfoVerificationRecord;
    }

    private List<List<String>> parseFileToRowList(String filePath) {
        // 1. 读取文件
        File pdf = new File(filePath);

        //页面所有table的记录，每一个元素代表下面一条记录cellList
        List<List<String>> rowList = new ArrayList<>();

        // 2. pdfbox读取PDDocument
        try (PDDocument pdfDocument = PDDocument.load(pdf)) {
            // 3. tabula新建ObjectExtractor和NurminenDetectionAlgorithm，同时准备接收表格Rectangle的结构
            ObjectExtractor objectExtractor = new ObjectExtractor(pdfDocument);
            SpreadsheetDetectionAlgorithm detectionAlgorithm = new SpreadsheetDetectionAlgorithm();
            Map<Integer, List<Rectangle>> pageNumber2RectangleListMap = new HashMap<>();//key为页的序号， value为对应的Rectangle的list

            // 4. 获取每页的PageIterator
            PageIterator pageIterator = objectExtractor.extract();

            // 5. 解析每页的Rectangle
            // 如果单页pdf中有多个Rectangle，则解析出来的List<Rectangle>会有多个对象
            while (pageIterator.hasNext()) {
                Page page = pageIterator.next();
                List<Rectangle> rectangleList = detectionAlgorithm.detect(page);
                if (rectangleList.size() > 0) {
                    pageNumber2RectangleListMap.put(page.getPageNumber(), rectangleList);
                }
            }

            // 6.通过table位置获取表格具体内容
            SpreadsheetExtractionAlgorithm extractionAlgorithm = new SpreadsheetExtractionAlgorithm();

            // 如果单页pdf中有多个表格，则解析出来的List<Rectangle>会有多个对象
            for (Map.Entry<Integer, List<Rectangle>> entry : pageNumber2RectangleListMap.entrySet()) {
                Page page = objectExtractor.extract(entry.getKey());
                Rectangle rectangle = null;

                List<Rectangle> rectangleList = entry.getValue();
                for (Rectangle r : rectangleList) {
                    double rectangleHeight = r.getHeight();
                    if (Double.compare(rectangleHeight, 0) > 0) {
                        rectangle = r;
                        break;
                    }
                }
                if (rectangle == null) {
                    throw new RuntimeException("rectangle is null.");
                }

                if (entry.getKey() > 1) {
                    rectangle.setTop(rectangle.getTop() - 20);
                }
                rectangle.setBottom(rectangle.getBottom() + 5);
                Page area = page.getArea(rectangle);

                // 如果每页有多个表格，解析每一个table
                List<Table> tableList = extractionAlgorithm.extract(area);
                for (Table table : tableList) {
                    for (int i = 0; i < table.getRowCount(); i++) {
                        List<String> cellList = new ArrayList<>();//一条记录，每个单元格占一个元素
                        for (int j = 0; j < table.getColCount(); j++) {
                            cellList.add(table.getCell(i, j).getText(false));
                        }
                        rowList.add(cellList);
                    }
                }
            }
        } catch (Exception e) {
            throw new RuntimeException(e.getMessage());
        }

        return rowList;
    }

    private void parseListToBO(List<List<String>> rowList, CDBDCPersonalHousingInfoQueryRecord personalHousingInfoQueryRecord) {
        String sectionName = ""; //有用的信息段标识

        List<CDBDCPersonalHousingInfoQueryRecord.ApplicationInfo> applicationInfoList = new ArrayList<>();
        List<CDBDCPersonalHousingInfoQueryRecord.QueryResult> queryResultList = null;

        for (int i = 0; i < rowList.size(); i++) {
            List<String> cellList = rowList.get(i);
            if (StringUtils.equals(cellList.get(0), "申请信息")) {
                sectionName = "申请信息";
                continue;
            } else if (StringUtils.equals(cellList.get(0), "被查询人")) {
                continue;
            } else if (StringUtils.equals(cellList.get(0), "查询结果")) {
                sectionName = "查询结果";
                continue;
            } else if (StringUtils.equals(cellList.get(0), "业务件号(合同备案号)")) {
                continue;
            } else if (StringUtils.equals(cellList.get(0), "无房屋查询记录")) {
                break;
            }

            switch (sectionName) {
                case "申请信息":
                    CDBDCPersonalHousingInfoQueryRecord.ApplicationInfo applicationInfo =
                            new CDBDCPersonalHousingInfoQueryRecord.ApplicationInfo();
                    applicationInfo.setRespondent(cellList.get(0));
                    applicationInfo.setIdNo(cellList.get(1));
                    applicationInfoList.add(applicationInfo);
                    personalHousingInfoQueryRecord.setApplicationInfoList(applicationInfoList);
                    break;
                case "查询结果":
                    if (Objects.isNull(queryResultList)) {
                        queryResultList = new ArrayList<>();
                    }
                    CDBDCPersonalHousingInfoQueryRecord.QueryResult queryResult =
                            new CDBDCPersonalHousingInfoQueryRecord.QueryResult();
                    queryResult.setItemNumber(cellList.get(0));
                    queryResult.setName(cellList.get(1));
                    queryResult.setHouseAddress(cellList.get(2));
                    queryResult.setGainingMethod(cellList.get(3));
                    queryResult.setBuildingStructure(cellList.get(4));
                    queryResult.setHouseUsage(cellList.get(5));
                    queryResult.setFloorSpace(cellList.get(6));
                    queryResult.setRegistrationTime(cellList.get(7));
                    queryResult.setState(cellList.get(8));
                    queryResult.setComment(cellList.get(9));
                    queryResultList.add(queryResult);
            }
        }

        personalHousingInfoQueryRecord.setApplicationInfoList(applicationInfoList);
        personalHousingInfoQueryRecord.setQueryResultList(queryResultList);
    }

    private void parseListToBO(List<List<String>> rowList, CDBDCHousingInfoQueryRecord housingInfoQueryRecord) {
        String sectionName = "";

        CDBDCHousingInfoQueryRecord.BasicInfo basicInfo = new CDBDCHousingInfoQueryRecord.BasicInfo();
        CDBDCHousingInfoQueryRecord.OwnershipInfo ownershipInfo = new CDBDCHousingInfoQueryRecord.OwnershipInfo();
        List<CDBDCHousingInfoQueryRecord.OwnerInfo> ownerInfoList = new ArrayList<>();
        CDBDCHousingInfoQueryRecord.ContractFilingInfo contractFilingInfo = null;
        CDBDCHousingInfoQueryRecord.Buyer buyer = null;
        List<CDBDCHousingInfoQueryRecord.BuyerInfo> buyerInfoList = new ArrayList<>();
        CDBDCHousingInfoQueryRecord.Seller seller = null;
        List<CDBDCHousingInfoQueryRecord.SellerInfo> sellerInfoList = new ArrayList<>();
        CDBDCHousingInfoQueryRecord.OtherInfo otherInfo = new CDBDCHousingInfoQueryRecord.OtherInfo();
        List<CDBDCHousingInfoQueryRecord.MortgageInfo> mortgageInfoList = null;
        List<CDBDCHousingInfoQueryRecord.HistoricalChangeInfo> historicalChangeInfoList = null;

        for (List<String> cellList : rowList) {
            if (StringUtils.equals(cellList.get(0), "基本信息")) {
                sectionName = "基本信息";
                continue;
            } else if (StringUtils.equals(cellList.get(0), "所在区")) {
                continue;
            } else if (StringUtils.equals(cellList.get(0), "所有权信息")) {
                sectionName = "所有权信息";
                continue;
            } else if (StringUtils.equals(cellList.get(0), "所有权人")) {
                continue;
            } else if (StringUtils.equals(cellList.get(0), "所有方式")) {
                sectionName = "所有方式";
            } else if (StringUtils.equals(cellList.get(0), "备  注")) {
                sectionName = "备  注";
            } else if (StringUtils.equals(cellList.get(0), "合同备案信息")) {
                sectionName = "合同备案信息";
                continue;
            } else if (StringUtils.equals(cellList.get(0), "买受人")) {
                sectionName = "买受人";
                continue;
            } else if (StringUtils.equals(cellList.get(0), "出卖人")) {
                sectionName = "出卖人";
                continue;
            } else if (StringUtils.equals(cellList.get(0), "抵押信息")) {
                sectionName = "抵押信息";
                continue;
            } else if (StringUtils.equals(cellList.get(0), "权利设定时间")) {
                continue;
            } else if (StringUtils.equals(cellList.get(0), "限制登记信息")) {
                sectionName = "限制登记信息";
                continue;
            } else if (StringUtils.equals(cellList.get(0), "其他信息")) {
                sectionName = "其他信息";
                continue;
            } else if (StringUtils.equals(cellList.get(0), "历史变动信息")) {
                sectionName = "历史变动信息";
                continue;
            }

            switch (sectionName) {
                case "基本信息":
                    basicInfo.setHostDistrict(cellList.get(0));
                    basicInfo.setStreet(cellList.get(1));
                    basicInfo.setDoorPlate(cellList.get(2));
                    basicInfo.setAttachedNumber(cellList.get(3));
                    basicInfo.setBuildingNumber(cellList.get(4));
                    basicInfo.setUnit(cellList.get(5));
                    basicInfo.setFloor(cellList.get(6));
                    basicInfo.setRoomNumber(cellList.get(7));
                    basicInfo.setPlanningUsage(cellList.get(8));
                    basicInfo.setStructure(cellList.get(9));
                    basicInfo.setStructureArea(cellList.get(10));
                    break;
                case "所有权信息":
                    CDBDCHousingInfoQueryRecord.OwnerInfo ownerInfo = new CDBDCHousingInfoQueryRecord.OwnerInfo();
                    ownerInfo.setOwner(cellList.get(0));
                    ownerInfo.setIdNo(cellList.get(1));
                    ownerInfo.setCertificateNumber(cellList.get(2));
                    ownerInfo.setShare(cellList.get(3));
                    ownerInfoList.add(ownerInfo);
                    break;
                case "所有方式":
                    ownershipInfo.setOwningMethod(cellList.get(1));
                    ownershipInfo.setGainingMethod(cellList.get(3));
                    ownershipInfo.setGainingTime(cellList.get(5));
                    break;
                case "备  注":
                    ownershipInfo.setComment(cellList.get(1));
                    break;
                case "合同备案信息":
                    if (StringUtils.equals(cellList.get(0), "无")){
                        break;
                    }
                    if (Objects.isNull(contractFilingInfo)) {
                        contractFilingInfo = new CDBDCHousingInfoQueryRecord.ContractFilingInfo();
                    }
                    if (StringUtils.equals(cellList.get(0), "存量房买卖合同签订时间")) {
                        contractFilingInfo.setSaleContractSignedDate(cellList.get(1));
                    } else if (StringUtils.equals(cellList.get(0), "商品房定购时间")) {
                        contractFilingInfo.setCommercialHousingPurchaseDate(cellList.get(1));
                        contractFilingInfo.setCommercialHousingContractDraftingDate(cellList.get(3));
                        contractFilingInfo.setCommercialHousingContractFilingDate(cellList.get(5));
                    } else if (StringUtils.equals(cellList.get(0), "预售许可证号")) {
                        contractFilingInfo.setPresaleLicenseNumber(cellList.get(1));
                        contractFilingInfo.setProjectName(cellList.get(3));
                    }
                    break;
                case "买受人":
                    if (Objects.isNull(buyer)) {
                        buyer = new CDBDCHousingInfoQueryRecord.Buyer();
                    }
                    CDBDCHousingInfoQueryRecord.BuyerInfo buyerInfo = new CDBDCHousingInfoQueryRecord.BuyerInfo();
                    buyerInfo.setName(cellList.get(0));
                    buyerInfo.setIdType(cellList.get(1));
                    buyerInfo.setIdNo(cellList.get(2));
                    buyerInfoList.add(buyerInfo);
                    break;
                case "出卖人":
                    if (Objects.isNull(seller)) {
                        seller = new CDBDCHousingInfoQueryRecord.Seller();
                    }
                    CDBDCHousingInfoQueryRecord.SellerInfo sellerInfo = new CDBDCHousingInfoQueryRecord.SellerInfo();
                    sellerInfo.setName(cellList.get(0));
                    sellerInfoList.add(sellerInfo);
                    break;
                case "抵押信息":
                    if (StringUtils.equals(cellList.get(0), "无")) {
                        break;
                    }
                    if (Objects.isNull(mortgageInfoList)) {
                        mortgageInfoList = new ArrayList<>();
                    }
                    CDBDCHousingInfoQueryRecord.MortgageInfo mortgageInfo = new CDBDCHousingInfoQueryRecord.MortgageInfo();
                    mortgageInfo.setRightEstablishmentTime(cellList.get(0));
                    mortgageInfo.setMortgagee(cellList.get(1));
                    mortgageInfo.setDebtor(cellList.get(2));
                    mortgageInfo.setMortgagedArea(cellList.get(3));
                    mortgageInfo.setSecuredClaimAmount(cellList.get(4));
                    mortgageInfo.setDebtPerformancePeriod(cellList.get(5));
                    mortgageInfo.setStatus(cellList.get(6));
                    mortgageInfo.setMortgageNo(cellList.get(7));
                    mortgageInfoList.add(mortgageInfo);
                    break;
                case "限制登记信息":
                    housingInfoQueryRecord.setRestrictedRegistrationInfo(cellList.get(0));
                    break;
                case "其他信息":
                    otherInfo.setIsCollected(cellList.get(1));
                    break;
                case "历史变动信息":
                    if (Objects.isNull(historicalChangeInfoList)) {
                        historicalChangeInfoList = new ArrayList<>();
                    }
                    CDBDCHousingInfoQueryRecord.HistoricalChangeInfo historicalChangeInfo
                            = new CDBDCHousingInfoQueryRecord.HistoricalChangeInfo();
                    historicalChangeInfo.setOwner(cellList.get(0));
                    historicalChangeInfo.setGainingMethod(cellList.get(1));
                    historicalChangeInfo.setGainingTime(cellList.get(2));
                    historicalChangeInfoList.add(historicalChangeInfo);
                    break;
            }
        }
        housingInfoQueryRecord.setBasicInfo(basicInfo);
        ownershipInfo.setOwnerInfoList(ownerInfoList);
        housingInfoQueryRecord.setOwnershipInfo(ownershipInfo);
        housingInfoQueryRecord.setContractFilingInfo(contractFilingInfo);
        if (Objects.nonNull(buyer)) {
            buyer.setBuyerInfo(buyerInfoList);
        }
        housingInfoQueryRecord.setBuyer(buyer);
        if (Objects.nonNull(seller)) {
            seller.setSellerList(sellerInfoList);
        }
        housingInfoQueryRecord.setSeller(seller);
        housingInfoQueryRecord.setMortgageInfoList(mortgageInfoList);
        housingInfoQueryRecord.setOtherInfo(otherInfo);
        housingInfoQueryRecord.setHistoricalChangeInfo(historicalChangeInfoList);
    }

    private boolean hasEmptyValueBo(CDBDCHousingInfoQueryRecord housingInfoQueryRecord) {
        boolean hasEmptyHistoricalChangeInfo = false;
        for (CDBDCHousingInfoQueryRecord.HistoricalChangeInfo historicalChangeInfo : housingInfoQueryRecord.getHistoricalChangeInfo()) {
            if (StringUtils.isBlank(historicalChangeInfo.getOwner())) {
                hasEmptyHistoricalChangeInfo = true;
                break;
            }
        }
        return hasEmptyHistoricalChangeInfo;
    }

    private void parseHistoricalChangeInfo(String filePath, CDBDCHousingInfoQueryRecord housingInfoQueryRecord) {
        try {
            List<CDBDCHousingInfoQueryRecord.HistoricalChangeInfo> historicalChangeInfoList
                    = housingInfoQueryRecord.getHistoricalChangeInfo();
            String headerText = parsePdfHeaderText(filePath);
            String historicalChangeInfoStr = headerText.substring(headerText.lastIndexOf("取得时间") + 4, headerText.lastIndexOf("第"));
            // 可能会有多条
            Pattern pattern = Pattern.compile("\\d{4}-\\d{2}-\\d{2}");
            Matcher matcher = pattern.matcher(historicalChangeInfoStr);

            List<Integer> endIndexList = new ArrayList<>();
            while (matcher.find()) {
                endIndexList.add(matcher.end());
            }

            List<String> historicalChangeInfoTextList = new ArrayList<>();
            for (int i = 0; i < endIndexList.size(); i++) {
                String historicalChangeInfoText;
                if (i == 0) {
                    historicalChangeInfoText = historicalChangeInfoStr.substring(0, endIndexList.get(i));
                } else {
                    historicalChangeInfoText = historicalChangeInfoStr.substring(endIndexList.get(i - 1), endIndexList.get(i));
                }
                historicalChangeInfoTextList.add(historicalChangeInfoText);
            }

            for (String historicalChangeInfoText : historicalChangeInfoTextList) {
                if (StringUtils.isNotBlank(historicalChangeInfoText)) {
                    List<String> list = Splitter.on(StringUtils.SPACE).splitToList(historicalChangeInfoText.trim());
                    if (list.size() == 3 && list.get(2).trim().matches("\\d{4}-\\d{2}-\\d{2}")) {
                        CDBDCHousingInfoQueryRecord.HistoricalChangeInfo historicalChangeInfo
                                = new CDBDCHousingInfoQueryRecord.HistoricalChangeInfo();
                        historicalChangeInfo.setOwner(list.get(0));
                        historicalChangeInfo.setGainingMethod(list.get(1));
                        historicalChangeInfo.setGainingTime(list.get(2));
                        historicalChangeInfoList.add(historicalChangeInfo);
                    }
                }
            }

            List<CDBDCHousingInfoQueryRecord.HistoricalChangeInfo> historicalChangeInfos = historicalChangeInfoList.stream().distinct()
                    .filter(historicalChangeInfo -> StringUtils.isNotBlank(historicalChangeInfo.getOwner())).collect(Collectors.toList());

            housingInfoQueryRecord.setHistoricalChangeInfo(historicalChangeInfos);
        } catch (Exception e) {
            log.error("parseHistoricalChangeInfo failed.", e);
        }
    }

    private void parseListToBO(List<List<String>> rowList, CDBDCNetContractInfoQueryRecord netContractInfoQueryRecord) {
        String sectionName = ""; //有用的信息段标识

        CDBDCNetContractInfoQueryRecord.BasicInfo basicInfo = new CDBDCNetContractInfoQueryRecord.BasicInfo();
        CDBDCNetContractInfoQueryRecord.HousingInfo housingInfo = new CDBDCNetContractInfoQueryRecord.HousingInfo();
        CDBDCNetContractInfoQueryRecord.Buyer buyer = null;
        List<CDBDCNetContractInfoQueryRecord.BuyerInfo> buyerInfoList = new ArrayList<>();
        CDBDCNetContractInfoQueryRecord.Seller seller = null;
        List<CDBDCNetContractInfoQueryRecord.SellerInfo> sellerInfoList = new ArrayList<>();
        CDBDCNetContractInfoQueryRecord.PaymentInfo paymentInfo = new CDBDCNetContractInfoQueryRecord.PaymentInfo();
        List<CDBDCNetContractInfoQueryRecord.MortgageInfo> mortgageInfoList = null;

        for (List<String> cellList : rowList) {
            if (StringUtils.equals(cellList.get(0), "基本信息")) {
                sectionName = "基本信息";
                continue;
            } else if (StringUtils.equals(cellList.get(0), "房屋信息")) {
                sectionName = "房屋信息";
                continue;
            } else if (StringUtils.equals(cellList.get(0), "房屋地址") || StringUtils.equals(cellList.get(7), "套内")) {
                continue;
            } else if (StringUtils.equals(cellList.get(0), "出卖人")) {
                sectionName = "出卖人";
                continue;
            } else if (StringUtils.equals(cellList.get(0), "名称")) {
                continue;
            } else if (StringUtils.equals(cellList.get(0), "买受人")) {
                sectionName = "买受人";
                continue;
            } else if (StringUtils.equals(cellList.get(0), "合同备注")) {
                sectionName = "合同备注";
            } else if (StringUtils.equals(cellList.get(0), "付款信息")) {
                sectionName = "付款信息";
                continue;
            } else if (StringUtils.equals(cellList.get(0), "限制登记信息")) {
                sectionName = "限制登记信息";
                continue;
            } else if (StringUtils.equals(cellList.get(0), "抵押信息")) {
                sectionName = "抵押信息";
                continue;
            } else if (StringUtils.equals(cellList.get(0), "抵押件号")) {
                continue;
            }

            switch (sectionName) {
                case "基本信息":
                    basicInfo.setSignedOnlineNo(cellList.get(1));
                    basicInfo.setSignedOnlineType(cellList.get(3));
                    basicInfo.setSignedOnlineTime(cellList.get(5));
                    break;
                case "房屋信息":
                    CDBDCNetContractInfoQueryRecord.FloorArea floorArea = new CDBDCNetContractInfoQueryRecord.FloorArea();
                    housingInfo.setHouseAddress(cellList.get(0));
                    housingInfo.setBuildingNumber(cellList.get(1));
                    housingInfo.setUnit(cellList.get(2));
                    housingInfo.setFloor(cellList.get(3));
                    housingInfo.setRoomNumber(cellList.get(4));
                    housingInfo.setStructure(cellList.get(5));
                    housingInfo.setUsage(cellList.get(6));
                    floorArea.setInsideArea(cellList.get(7));
                    floorArea.setResidentialPoolArea(cellList.get(8));
                    floorArea.setTotalArea(cellList.get(9));
                    housingInfo.setTransactionPrice(cellList.get(10));
                    housingInfo.setFloorArea(floorArea);
                    break;
                case "出卖人":
                    if (Objects.isNull(seller)) {
                        seller = new CDBDCNetContractInfoQueryRecord.Seller();
                    }
                    CDBDCNetContractInfoQueryRecord.SellerInfo sellerInfo = new CDBDCNetContractInfoQueryRecord.SellerInfo();
                    sellerInfo.setName(cellList.get(0));
                    sellerInfo.setIdType(cellList.get(1));
                    sellerInfo.setIdNo(cellList.get(2));
                    sellerInfoList.add(sellerInfo);
                    break;
                case "买受人":
                    if (Objects.isNull(buyer)) {
                        buyer = new CDBDCNetContractInfoQueryRecord.Buyer();
                    }
                    CDBDCNetContractInfoQueryRecord.BuyerInfo buyerInfo = new CDBDCNetContractInfoQueryRecord.BuyerInfo();
                    buyerInfo.setName(cellList.get(0));
                    buyerInfo.setIdType(cellList.get(1));
                    buyerInfo.setIdNo(cellList.get(2));
                    buyerInfo.setShare(cellList.get(3));
                    buyerInfoList.add(buyerInfo);
                    break;
                case "合同备注":
                    if (Objects.isNull(buyer)) {
                        buyer = new CDBDCNetContractInfoQueryRecord.Buyer();
                    }
                    buyer.setContractComment(cellList.get(1));
                    break;
                case "付款信息":
                    paymentInfo.setPaymentType(cellList.get(1));
                    paymentInfo.setLendingBank(cellList.get(3));
                    paymentInfo.setLoanPeriod(cellList.get(5));
                    break;
                case "限制登记信息":
                    netContractInfoQueryRecord.setRestrictedRegistrationInfo(cellList.get(0));
                    break;
                case "抵押信息":
                    if (StringUtils.equals(cellList.get(0), "无")) {
                        break;
                    }
                    if (Objects.isNull(mortgageInfoList)) {
                        mortgageInfoList = new ArrayList<>();
                    }
                    CDBDCNetContractInfoQueryRecord.MortgageInfo mortgageInfo = new CDBDCNetContractInfoQueryRecord.MortgageInfo();
                    mortgageInfo.setMortgageNo(cellList.get(0));
                    mortgageInfo.setMortgagee(cellList.get(1));
                    mortgageInfo.setDebtor(cellList.get(2));
                    mortgageInfo.setMortgagedArea(cellList.get(3));
                    mortgageInfo.setSecuredClaimAmount(cellList.get(4));
                    mortgageInfo.setDebtPerformancePeriod(cellList.get(5));
                    mortgageInfo.setStatus(cellList.get(6));
                    mortgageInfo.setRightEstablishmentTime(cellList.get(7));
                    mortgageInfoList.add(mortgageInfo);
                    break;
            }
        }
        netContractInfoQueryRecord.setBasicInfo(basicInfo);
        netContractInfoQueryRecord.setHousingInfo(housingInfo);
        if (Objects.nonNull(seller)) {
            seller.setSellerInfoList(sellerInfoList);
        }
        netContractInfoQueryRecord.setSeller(seller);
        if (Objects.nonNull(buyer)) {
            buyer.setBuyerInfoList(buyerInfoList);
        }
        netContractInfoQueryRecord.setBuyer(buyer);
        netContractInfoQueryRecord.setPaymentInfo(paymentInfo);
        netContractInfoQueryRecord.setMortgageInfoList(mortgageInfoList);
    }

    private void parseListToBO(List<List<String>> rowList, CDBDCTradeHousingInfoVerificationRecord tradeHousingInfoVerificationRecord) {
        String sectionName = ""; //有用的信息段标识

        CDBDCTradeHousingInfoVerificationRecord.BasicInfo basicInfo = new CDBDCTradeHousingInfoVerificationRecord.BasicInfo();
        CDBDCTradeHousingInfoVerificationRecord.OtherInfo otherInfo = new CDBDCTradeHousingInfoVerificationRecord.OtherInfo();
        List<CDBDCTradeHousingInfoVerificationRecord.OwnerInfo> ownerInfoList = new ArrayList<>();

        for (int i = 0; i < rowList.size(); i++) {
            List<String> cellList = rowList.get(i);
            if (StringUtils.equals(cellList.get(0), "基本信息")) {
                sectionName = "基本信息";
                continue;
            } else if (StringUtils.equals(cellList.get(0), "所在区")) {
                continue;
            } else if (StringUtils.equals(cellList.get(0), "所有权人")) {
                sectionName = "所有权人";
                continue;
            } else if (StringUtils.equals(cellList.get(0), "所有方式")) {
                sectionName = "所有方式";
            } else if (StringUtils.equals(cellList.get(0), "备  注")) {
                sectionName = "备  注";
            } else if (StringUtils.equals(cellList.get(0), "其他信息")) {
                continue;
            } else if (StringUtils.equals(cellList.get(0), "是否抵押")) {
                sectionName = "是否抵押";
            } else if (StringUtils.equals(cellList.get(0), "是否是保障住房")) {
                sectionName = "是否是保障住房";
            } else if (cellList.get(0).contains("提示信息")) {
                sectionName = "提示信息";
            }

            switch (sectionName) {
                case "基本信息":
                    basicInfo.setHostDistrict(cellList.get(0));
                    basicInfo.setStreet(cellList.get(1));
                    basicInfo.setDoorPlate(cellList.get(2));
                    basicInfo.setAttachedNumber(cellList.get(3));
                    basicInfo.setBuildingNumber(cellList.get(4));
                    basicInfo.setUnit(cellList.get(5));
                    basicInfo.setFloor(cellList.get(6));
                    basicInfo.setRoomNumber(cellList.get(7));
                    basicInfo.setPlanningUsage(cellList.get(8));
                    basicInfo.setStructure(cellList.get(9));
                    basicInfo.setStructureArea(cellList.get(10));
                    break;
                case "所有权人":
                    CDBDCTradeHousingInfoVerificationRecord.OwnerInfo ownerInfo = new CDBDCTradeHousingInfoVerificationRecord.OwnerInfo();
                    ownerInfo.setOwner(cellList.get(0));
                    ownerInfo.setCertificateNumber(cellList.get(1));
                    ownerInfoList.add(ownerInfo);
                    break;
                case "所有方式":
                    basicInfo.setOwningMethod(cellList.get(1));
                    basicInfo.setGainingMethod(cellList.get(3));
                    basicInfo.setGainingTime(cellList.get(5));
                    basicInfo.setRecordSigningTime(cellList.get(7));
                    break;
                case "备  注":
                    basicInfo.setComment(cellList.get(1));
                case "是否抵押":
                    otherInfo.setIsPledge(cellList.get(1));
                    otherInfo.setIsRestrict(cellList.get(3));
                    otherInfo.setIsLevy(cellList.get(5));
                    break;
                case "是否是保障住房":
                    otherInfo.setIsSubsidizedHousing(cellList.get(1));
                    otherInfo.setIsPayMaintenanceFund(cellList.get(3));
                    otherInfo.setIsLeaseFiling(cellList.get(5));
                    break;
                case "提示信息":
                    otherInfo.setPromptMessage(cellList.get(0).substring(5));
                    break;
            }
        }

        basicInfo.setOwnerInfoList(ownerInfoList);
        tradeHousingInfoVerificationRecord.setBasicInfo(basicInfo);
        tradeHousingInfoVerificationRecord.setOtherInfo(otherInfo);
    }

    public static void main(String[] args) {
        CDBDCPdfParser cdbdcPdfParser = new CDBDCPdfParser();

        String filePath = "D:\\data\\file\\cdbdc\\chrome-cdzjryb-bdc_bdcsj_0_0.pdf";
        ResponseData<String> responseData = cdbdcPdfParser.parseCDBDCPdfToJson("", filePath);
        System.out.println(responseData.getData());

        filePath = "D:\\data\\file\\cdbdc\\chrome-cdzjryb-bdc_bdcsj_1_1.pdf";
        responseData = cdbdcPdfParser.parseCDBDCPdfToJson("", filePath);
        System.out.println(responseData.getData());

        filePath = "D:\\data\\file\\cdbdc\\chrome-cdzjryb-bdc_bdcsj_1_2.pdf";
        responseData = cdbdcPdfParser.parseCDBDCPdfToJson("", filePath);
        System.out.println(responseData.getData());

        filePath = "D:\\data\\file\\cdbdc\\chrome-cdzjryb-bdc_bdcsj_1_3.pdf";
        responseData = cdbdcPdfParser.parseCDBDCPdfToJson("", filePath);
        System.out.println(responseData.getData());

        filePath = "D:\\data\\file\\cdbdc\\chrome-cdzjryb-bdc_bdcsj_2_1.pdf";
        responseData = cdbdcPdfParser.parseCDBDCPdfToJson("", filePath);
        System.out.println(responseData.getData());

        filePath = "D:\\data\\file\\cdbdc\\chrome-cdzjryb-bdc_bdcsj_2_2.pdf";
        responseData = cdbdcPdfParser.parseCDBDCPdfToJson("", filePath);
        System.out.println(responseData.getData());

        filePath = "D:\\data\\file\\cdbdc\\chrome-cdzjryb-bdc_bdcsj_2_3.pdf";
        responseData = cdbdcPdfParser.parseCDBDCPdfToJson("", filePath);
        System.out.println(responseData.getData());

        filePath = "D:\\data\\file\\cdbdc\\chrome-cdzjryb-bdc_bdcsj_3_1.pdf";
        responseData = cdbdcPdfParser.parseCDBDCPdfToJson("", filePath);
        System.out.println(responseData.getData());

        filePath = "D:\\data\\file\\cdbdc\\chrome-cdzjryb-bdc_bdcsj_3_2.pdf";
        responseData = cdbdcPdfParser.parseCDBDCPdfToJson("", filePath);
        System.out.println(responseData.getData());

        filePath = "D:\\data\\file\\cdbdc\\chrome-cdzjryb-bdc_bdcsj_3_3.pdf";
        responseData = cdbdcPdfParser.parseCDBDCPdfToJson("", filePath);
        System.out.println(responseData.getData());
    }

}
